package com.ruoyi.rva.service.impl;

import com.ruoyi.rva.domain.RvaApp;
import com.ruoyi.rva.domain.RvaAppitem;
import com.ruoyi.rva.domain.RvaMap;
import com.ruoyi.rva.mapper.RvaAppMapper;
import com.ruoyi.rva.service.IRvaCrudService;
import com.ruoyi.rva.service.IRvaTreeCrudService;
import com.ruoyi.rva.util.RvaConstants;
import com.ruoyi.rva.util.RvaUtils;
import com.ruoyi.rva.util.RvaVelocityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class RvaTreeCrudServiceImpl implements IRvaTreeCrudService {

    private final IRvaCrudService crudService;

    private final RvaAppMapper appMapper;

    private static final String PARAM_TCRUD_ID = "treeCrudId";

    @Override
    public List<RvaMap<String, Object>> selectNodes(String appId, RvaMap req) {
        RvaApp app = appMapper.selectRvaAppById(appId);
        List<RvaAppitem> navTreeCruds = app.getAppItemsByType("nav");
        if (navTreeCruds.size() == 0) {
            navTreeCruds = app.getAppItems();
        }
        String treeCrudId = req.getString(PARAM_TCRUD_ID);
        req.rvaPut("pageSize", 100L);
        List<RvaMap<String, Object>> results = new ArrayList<>();
        if (RvaUtils.isEmpty(treeCrudId)) {
            navTreeCruds.forEach(item -> {
                if (RvaUtils.isEmpty(item.getParentId())) {
                    addToResults(req, results, item);
                }
            });
        } else {
            Optional<RvaAppitem> first = navTreeCruds.stream().filter(item -> item.getRelatedAppId().equals(treeCrudId)).findFirst();
            if (first.isPresent()) {
                navTreeCruds.forEach(item -> {
                    if (first.get().getId().equals(item.getParentId())) {
                        addToResults(req, results, item);
                    }
                });
            }

        }
        return results;
    }

    private void addToResults(RvaMap req, List<RvaMap<String, Object>> results, RvaAppitem item) {
        if ("list".equals(item.getSubType())) {
            results.addAll(queryList(item.getRelatedAppId(), req));
        } else {
            results.add(new RvaMap<String, Object>("label", item.getName())
                    .rvaPut(PARAM_TCRUD_ID, item.getRelatedAppId()).rvaPut(RvaConstants.PROP_KEY_VALUE, item.getRelatedAppId()));
        }
    }

    private List<RvaMap<String, Object>> queryList(String appId, RvaMap req) {
        List<RvaMap<String, Object>> list = crudService.selectList(appId, req);
        list.forEach(row -> {
            row.put("label", row.getString(RvaConstants.PROP_NAME_VALUE));
            row.put(PARAM_TCRUD_ID, appId);
        });
        return list;
    }

    private final RvaVelocityUtils velocityUtils;

    @Override
    public List<RvaAppitem> selectContents(String appId, RvaMap req) {
        RvaApp app = appMapper.selectRvaAppById(appId);
        List<RvaAppitem> navs = app.getAppItemsByType("nav");
        List<RvaAppitem> contents = app.getAppItemsByType("content");
        if (navs.size() == 0) {
            contents = app.getAppItems().stream().filter(rvaAppitem -> rvaAppitem.getRelatedAppId().equals(req.getString(RvaConstants.PROP_KEY_VALUE))).collect(Collectors.toList());
        }
        return (List<RvaAppitem>)contents.stream().filter(item -> velocityUtils.validateWithLoginUser(item.getShowIf(), req)).collect(Collectors.toList());
    }
}
